package com.easy.generator;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDate;
import java.util.Locale;

/**
 * @author easy
 * @date 2025年07月05日 19:36
 */
public class TokenGenerator {
    private static final String CLASS_NAME = "TokenUtil";
    private static final String PACKAGE_NAME = Easy.UTIL_PACKAGE;


    private static final String CLASS_TEMPLATE =
                    "package "+PACKAGE_NAME+";\n" +
                    "\n" +
                    "import cn.hutool.jwt.JWT;\n" +
                    "import cn.hutool.jwt.JWTUtil;\n" +
                    "import cn.hutool.jwt.JWTValidator;\n" +
                    "\n" +
                    "import java.util.Date;\n" +
                    "import java.util.HashMap;\n" +
                    "import java.util.Map;\n" +
                    "import java.util.Set;\n" +
                    "\n" +
                    "public class TokenUtil {\n" +
                    "    public static final String TOKEN_HEADER = \"Authorization\";\n" +
                    "    public static final String USERID = \"userid\";\n" +
                    "    public static final String USERNAME = \"username\";\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 签名  每次重启服务签名都会动态生成\n" +
                    "     */\n" +
                    "    public static final String SECRET_KEY = \"Easy\";\n" +
                    "    /**\n" +
                    "     * token有效时间\n" +
                    "     */\n" +
                    "    private static final long EXPIRATION = 86400000; // 24小时\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 生成token\n" +
                    "     *\n" +
                    "     * @param map 需要加载的数据\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public static String generateToken(Map<String, Object> map) {\n" +
                    "        JWT jwt = JWT.create();\n" +
                    "        Set<String> keys = map.keySet();\n" +
                    "        for (String key : keys) {\n" +
                    "            jwt.setPayload(key, map.get(key));\n" +
                    "        }\n" +
                    "        jwt.setExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION));\n" +
                    "        String token = jwt.setKey(SECRET_KEY.getBytes()).sign();\n" +
                    "        return token;\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取token中的信息\n" +
                    "     * @param token\n" +
                    "     * @param key\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public static Object getPayload(String token, String key) {\n" +
                    "        JWT jwt = cn.hutool.jwt.JWTUtil.parseToken(token);\n" +
                    "        Object payload =jwt.getPayload(key);\n" +
                    "        return payload;\n" +
                    "    }\n" +
                    "\n" +
                    "    public static boolean verifyToken(String token) {\n" +
                    "        //验证签名\n" +
                    "        if (!JWTUtil.verify(token, SECRET_KEY.getBytes())) {\n" +
                    "            throw new RuntimeException(\"签名异常\");\n" +
                    "        }\n" +
                    "        try {\n" +
                    "            JWTValidator.of(token).validateDate();\n" +
                    "        } catch (Exception e) {\n" +
                    "            throw new RuntimeException(\"签名过期\");\n" +
                    "        }\n" +
                    "        return true;\n" +
                    "    }\n" +
                    "}\n";
    public static void generateUtil() throws IOException {
        String content = String.format(CLASS_TEMPLATE, LocalDate.now());
        File outputFile = new File(Easy.PROJECT_ABSOLUTE_URL + Easy.SRC_DIR + Easy.convertPackagePath(PACKAGE_NAME) + "/" + CLASS_NAME + ".java");
        try (FileWriter writer = new FileWriter(outputFile)) {
            writer.write(content);
        }
    }

    private static final String LOGIN_CONTROLLER_PACKAGE = Easy.CONTROLLER_PACKAGE;
    private static final String LOGIN_CONTROLLER_NAME = "LoginController";
    private static final String LOGIN_SERVICE_NAME = Easy.LOGIN_ENTITY + "Service";
    private static final String LOGIN_SERVICE_VAR_NAME = Easy.LOGIN_ENTITY.toLowerCase(Locale.ROOT)+"Service";
    private static final String LOGIN_BEAN_NAME = Easy.LOGIN_ENTITY;
    private static final String LOGIN_BEAN_VAR_NAME = Easy.LOGIN_ENTITY.toLowerCase(Locale.ROOT);
    private static final String LOGIN_USERNAME_FIELD_NAME = Easy.LOGIN_NAME_FIELD;
    private static final String LOGIN_USERNAME_GET_METHOD = "get"+Easy.LOGIN_NAME_FIELD.substring(0,1).toUpperCase(Locale.ROOT)+Easy.LOGIN_NAME_FIELD.substring(1);
    private static final String LOGIN_PASSWORD_FIELD_NAME = Easy.LOGIN_PASSWORD_FIELD;
    private static final String LOGIN_PASSWORD_GET_METHOD = "get"+Easy.LOGIN_PASSWORD_FIELD.substring(0,1).toUpperCase(Locale.ROOT)+Easy.LOGIN_PASSWORD_FIELD.substring(1);

    private static final String LOGIN_CONTROLLER_TEMPLATE =
            "package "+LOGIN_CONTROLLER_PACKAGE+";\n" +
            "\n" +
            "import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\n" +
            "import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;\n" +
            "import "+Easy.BEAN_PACKAGE+".*;\n" +
            "import "+Easy.SERVICE_PACKAGE+".*;\n" +
            "import "+Easy.UTIL_PACKAGE+".*;\n" +
            "import org.springframework.beans.factory.annotation.Autowired;\n" +
            "import org.springframework.web.bind.annotation.*;\n" +
            "\n" +
            "import java.util.HashMap;\n" +
            "\n" +
            "@RestController\n" +
            "@CrossOrigin\n" +
            "public class "+LOGIN_CONTROLLER_NAME+" {\n" +
            "    @Autowired\n" +
            "    "+LOGIN_SERVICE_NAME+" "+LOGIN_SERVICE_VAR_NAME+";\n" +
            "\n" +
            "    @RequestMapping(\"/dologin\")\n" +
            "    public Result doLogin("+LOGIN_BEAN_NAME+" "+LOGIN_BEAN_VAR_NAME+", @RequestParam(\"key\") String key, @RequestParam(\"code\") String code) {\n" +
            "        boolean flag = InnerCaptchaUtil.verifyCaptcha(key, code);\n" +
            "        if (!flag) {\n" +
            "            throw new RuntimeException(\"验证码错误\");\n" +
            "        }\n" +
            "        if (Util.isEmpty("+LOGIN_BEAN_VAR_NAME+"."+LOGIN_USERNAME_GET_METHOD+"(), "+LOGIN_BEAN_VAR_NAME+"."+LOGIN_PASSWORD_GET_METHOD+"())) {\n" +
            "            throw new RuntimeException(\"数据格式错误\");\n" +
            "        }\n" +
            "        LambdaQueryWrapper<"+LOGIN_BEAN_NAME+"> queryWrapper = new LambdaQueryWrapper<>();\n" +
            "        queryWrapper.eq("+LOGIN_BEAN_NAME+"::"+LOGIN_USERNAME_GET_METHOD+", "+LOGIN_BEAN_VAR_NAME+"."+LOGIN_USERNAME_GET_METHOD+"());\n" +
            "        "+LOGIN_BEAN_NAME+" db"+LOGIN_BEAN_NAME+" = "+LOGIN_SERVICE_VAR_NAME+".getOne(queryWrapper);\n" +
            "        if (db"+LOGIN_BEAN_NAME+"==null) {\n" +
            "            throw new RuntimeException(\"用户名或密码错误\");\n" +
            "        }\n" +
            "        flag=PasswordDecode.verify("+LOGIN_BEAN_VAR_NAME+"."+LOGIN_PASSWORD_GET_METHOD+"(), db"+LOGIN_BEAN_NAME+"."+LOGIN_PASSWORD_GET_METHOD+"());\n" +
            "        if (!flag) {\n" +
            "            throw new RuntimeException(\"用户名或密码错误\");\n" +
            "        }else{\n" +
            "            HashMap<String,Object> map = new HashMap<>();\n" +
            "            map.put(TokenUtil.USERID, db"+LOGIN_BEAN_NAME+".getId());\n" +
            "            map.put(TokenUtil.USERNAME, db"+LOGIN_BEAN_NAME+"."+LOGIN_USERNAME_GET_METHOD+"());\n" +
            "            return Result.success(TokenUtil.generateToken(map));\n" +
            "        }\n" +
            "    }\n" +
            "\n" +
            "    @PostMapping(\"/register\")\n" +
            "    public Result register(@RequestBody "+LOGIN_BEAN_NAME+" "+LOGIN_BEAN_VAR_NAME+") {\n" +
            "        if(Util.isNull("+LOGIN_BEAN_VAR_NAME+"."+LOGIN_USERNAME_GET_METHOD+"(), "+LOGIN_BEAN_VAR_NAME+"."+LOGIN_PASSWORD_GET_METHOD+"())) {\n" +
            "            throw new RuntimeException(\"数据格式错误\");\n" +
            "        }\n" +
            "        LambdaQueryWrapper<"+LOGIN_BEAN_NAME+"> queryWrapper = new LambdaQueryWrapper<>();\n" +
            "        queryWrapper.eq("+LOGIN_BEAN_NAME+"::"+LOGIN_USERNAME_GET_METHOD+", "+LOGIN_BEAN_VAR_NAME+"."+LOGIN_USERNAME_GET_METHOD+"());\n" +
            "        "+LOGIN_BEAN_NAME+" db"+LOGIN_BEAN_NAME+" = "+LOGIN_SERVICE_VAR_NAME+".getOne(queryWrapper);\n" +
            "        if(db"+LOGIN_BEAN_NAME+" != null) {\n" +
            "//            return Result.error(400, \"用户已存在\");\n" +
            "            throw new RuntimeException(\"用户已存在\");\n" +
            "        }\n" +
            "        return Result.success(200, \"注册成功\","+LOGIN_SERVICE_VAR_NAME+".save("+LOGIN_BEAN_VAR_NAME+"));\n" +
            "    }\n" +
            "\n" +
            "}\n";
    public static void generateLoginController() throws IOException {
        String content = String.format(LOGIN_CONTROLLER_TEMPLATE, LocalDate.now());
        File outputFile = new File(Easy.PROJECT_ABSOLUTE_URL + Easy.SRC_DIR + Easy.convertPackagePath(LOGIN_CONTROLLER_PACKAGE) + "/" + LOGIN_CONTROLLER_NAME + ".java");
        try (FileWriter writer = new FileWriter(outputFile)) {
            writer.write(content);
        }
    }
    public static void generate() throws IOException {
        Easy.initPackage(PACKAGE_NAME);
        Easy.initPackage(LOGIN_CONTROLLER_PACKAGE);
        generateUtil();
        generateLoginController();
    }

}
